home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / music / musgfa.zoo / makdosnd.lst next >
File List  |  1992-12-24  |  14KB  |  440 lines

  1. ' makdsnd.gfa  12 July 1991 modified 5 July 1992
  2. ' This program converts a *.tun file into a file of data which
  3. ' can be run by dosound (~xbios(32,L:...)). Pressing any key on
  4. ' the keyboard will interrupt the conversion and cause the data to
  5. ' be written out.  The name of the output file is  sound.dat
  6. ' programmed by Seymour Shlien in GFA Basic 3.5 on my 1040STE
  7. ' 624 Courtenay Avenue / Ottawa, Ontario, Canada  K2A 3B5
  8. ' The program is public domain and not for commercial use.
  9. DIM notes_to_microbeats%(12) ! duration code (1 - 12) to microbeat value
  10. DIM elapsed_microbeats%(3) !number of microbeats for each voice (bar lines)
  11. DIM seq%(3) !note sequence number in each voice during play
  12. DIM micro_beat%(3) ! accumulated microbeats for voice (for play)
  13. DIM next_event%(3) ! time for next note to sound for voice (for play)
  14. DIM play_stop%(3) ! kounter for stop playing -used in cue
  15. DIM note_tick%(3) ! time a note was sounded. Used for envelope
  16. DIM tone_envel%(300) ! loudness envelope 1 to 100 for each voice
  17. DIM voice_end_flag%(3) ! flag to signal end of voice
  18. DIM note%(3),duration%(3),draw_flag%(3) !last notes sounded
  19. DIM kount%(2),vclen%(2),repeat_sign%(2),repeat_count%(2)
  20. REM memory for storing music
  21. DIM tnote&(2,1000),mubeat%(3)
  22. DIM last_note_duration%(3) !need it if we correct an error with right button
  23. DIM music_mem&(40000)
  24. DIM music_cmp&(5000)
  25. DIM volum(3),decay(3)
  26. DEFMOUSE 0
  27. CLS
  28. voic%=1
  29. voic1%=voic%-1
  30. volum(0)=14
  31. volum(1)=13
  32. volum(2)=12
  33. decay(0)=0.08
  34. decay(1)=0.09
  35. decay(2)=0.13
  36. PRINT "This program converts a *.tun file"
  37. PRINT "into an *.XBS file. Select the"
  38. PRINT "desired file using the file"
  39. PRINT "selector. The program converts this"
  40. PRINT "file as it is playing it on the"
  41. PRINT "Atari sound chip. It stops when it"
  42. PRINT "plays the entire file or when"
  43. PRINT "you hit the space bar. It then"
  44. PRINT "records everything it played on"
  45. PRINT "the file sound.xbs."
  46. PRINT "... Hit space bar to continue."
  47. DO UNTIL key_interrupt$<>""
  48.   key_interrupt$=INKEY$
  49. LOOP
  50. FOR i%=0 TO 2
  51.   offset=volum(i%)
  52.   attenuation=decay(i%)
  53.   @make_tone_envelope(i%,offset,attenuation)
  54. NEXT i%
  55. @read_music_data
  56. @initialize_note_table
  57. @read_tune_file
  58. @play_tune
  59. ' @dosound
  60. @write_sound
  61. > PROCEDURE tnote_structure_doc
  62.   ' tnote array stores the pitch and duration value of every note
  63.   ' to be played for the three voices (tracks). The high byte contains
  64.   ' the duration code and other special codes. The low byte contains
  65.   ' the pitch code. The pitch code modulo 12 maps into the note letter
  66.   ' c,c#,d,d#,... b. If the pitch code is zero then a rest is assumed.
  67.   ' The duration code 0 to 12 map to note duration in the order that
  68.   ' the note duration sprites appear in the menu. Other codes 13 to 15
  69.   ' control repeats. Codes 16 and 17 are not fully implemented but allow
  70.   ' the inclusion of long rests in a particular voice. Other codes are
  71.   ' only used for the input /output files *.TUN for specifying key signature,
  72.   ' time signature, and tempo.
  73. RETURN
  74. > PROCEDURE read_music_data
  75.   @read_timconv_array
  76. RETURN
  77. > PROCEDURE read_timconv_array
  78.   LOCAL i%
  79.   REM for converting notes to microbeats
  80.   FOR i%=0 TO 12
  81.     READ notes_to_microbeats%(i%)
  82.   NEXT i%
  83.   DATA 3,6,12,18,24,36,48,72,96,144,2,4,8
  84.   ' whole note = 96 microbeats
  85. RETURN
  86. '
  87. '
  88. '
  89. > PROCEDURE yamaha_doc
  90.   ' I was not very successful using the sound or wave commands in gfa
  91.   ' basic to produce polyphonic music. (Its ok for chords). Furthermore
  92.   ' the envelope feature on the Yamaha chip produced problems that I could
  93.   ' not resolve. I therefore implemented the sound at a fairly low level
  94.   ' using BIOS commands. The following functions interface with the xbios
  95.   ' command 28. This is tricky since some of the registers are used for
  96.   ' disk i/o and damage to the disk can result. I put in extra protection
  97.   ' in this code which should never be commented out.
  98.   ' I decided to implement the music production this way rather than
  99.   ' using the xbios 32 play sequence command so that I can follow the
  100.   ' production of each note. Even though I am controlling the amplitude
  101.   ' envelope every 50 th of a second, as well as placing sprites on the
  102.   ' screen, there is ample time left over.
  103.   ' The make_tone_envelope function controls the linear rise and two
  104.   ' linear decay modes of the amplitude. The envelope is put into a table.
  105.   '
  106.   ' The procedure play_next_notes, polls all three voices to see whether
  107.   ' it is time to change the volume or pitch of a note. When it is
  108.   ' time to change it finds the next note and sets the time to change
  109.   ' that note based on the notes duration and the slowness of the music.
  110. RETURN
  111. > PROCEDURE initialize_note_table
  112.   ' Thanks ken
  113.   LOCAL note|
  114.   IF NOT u__init!
  115.     u__init!=TRUE
  116.     DIM u__period%(96)
  117.     FOR note|=0 TO 12
  118.       FOR o%=0 TO 7
  119.         u__period%(12*o%+note|)=125000/(2^o%*440*(2^(note|/12))/(2^(10/12))/16)+0.5
  120.       NEXT o%
  121.     NEXT note|
  122.   ENDIF
  123. RETURN
  124. > PROCEDURE set_tone_period(voice%,period%)
  125.   LOCAL reg%,period_low%,period_hi%,reg_val%
  126.   IF voice%<0 OR voice%>2
  127.     GOTO set_tone_err
  128.   ENDIF
  129.   reg%=voice%*2
  130.   period_low%=AND(period%,255)
  131.   period_hi%=SHR(AND(period%,&HF00),8)
  132.   period%=XBIOS(28,period_low%,reg%+128) !period% is not used anymore
  133.   music_mem&(memptr%)=SHL(reg%,8)+period_low%
  134.   INC memptr%
  135.   reg%=reg%+1
  136.   reg_val%=AND(XBIOS(28,0,reg%),&HF0) !must save hi bits
  137.   reg_val%=OR(AND(period_hi%,15),reg_val%) !combine low and hi bits
  138.   reg_val%=XBIOS(28,reg_val%,reg%+128) !output
  139.   music_mem&(memptr%)=SHL(reg%,8)+reg_val%
  140.   INC memptr%
  141.   GOTO set_tone_return
  142. set_tone_err:
  143.   STOP
  144. set_tone_return:
  145. RETURN
  146. > PROCEDURE disable_noise_channels
  147.   LOCAL reg_val%
  148.   reg_val%=XBIOS(28,0,7)
  149.   reg_val%=OR(AND(reg_val%,192),56)
  150.   reg_val=XBIOS(28,reg_val%,7+128)
  151.   music_mem&(memptr%)=SHL(7,8)+reg_val%
  152.   INC memptr%
  153. RETURN
  154. > PROCEDURE set_volume(voice%,level%)
  155.   ' level between 0 and 15 for constant volume
  156.   ' level 16 for waveform envelope
  157.   LOCAL reg%,reg_val%
  158.   IF voice%<0 OR voice>2 !check for legal voice number
  159.     GOTO set_volume_err
  160.   ENDIF
  161.   IF level%>31 OR level%<0
  162.     GOTO set_volume_err
  163.   ENDIF
  164.   reg%=8+voice%
  165.   regval%=XBIOS(28,0,reg%)
  166.   regval%=AND(regval%,&HE0) !save only top 3 bits
  167.   regval%=OR(regval%,AND(level%,31))
  168.   regval%=XBIOS(28,regval%,reg%+128)
  169.   music_mem&(memptr%)=SHL&(reg%,8)+regval%
  170.   INC memptr%
  171.   GOTO set_volume_return
  172. set_volume_err:
  173.   STOP
  174. set_volume_return:
  175. RETURN
  176. > PROCEDURE dosound
  177.   LOCAL i%
  178.   '  SPOKE &H484,PEEK(&H484) AND NOT 1
  179.   addr%=VARPTR(music_mem&(0))
  180.   PRINT addr%
  181.   FOR i%=0 TO 200
  182.     PRINT BYTE{addr%+i%};" ";
  183.   NEXT i%
  184.   ~XBIOS(32,L:VARPTR(music_mem&(0)))
  185. RETURN
  186. > PROCEDURE write_sound
  187.   LOCAL addr%
  188.   addr%=VARPTR(music_mem&(0))
  189.   BSAVE "sound.xbs",addr%,memptr%*2
  190. RETURN
  191. > PROCEDURE make_tone_envelope(num%,offset,attenuation)
  192.   LOCAL index%,val%,i%
  193.   index%=num%*100
  194.   FOR i%=0 TO 99
  195.     val%=offset-i%*attenuation
  196.     val%=MAX(val%,0)
  197.     val%=MIN(val%,15)
  198.     tone_envel%(i%+index%)=val%
  199.   NEXT i%
  200. RETURN
  201. > PROCEDURE play_tune
  202.   ' The procedure plays song number numb%.
  203.   ' The base_time% is set to the current time in ticks.
  204.   ' The function next_note is called repeatedly, to sound the next
  205.   ' note when it is time to do so. If a note has been sounded, we
  206.   ' draw it on the staff.
  207.   LOCAL i%,note_xposition%,k%
  208.   skoll%=0 ! rem scrolling is off
  209.   ' find voices
  210.   IF speed%>0
  211.     slowness=135/speed% !comment this statement when debugging
  212.   ELSE
  213.     slowness=2
  214.   ENDIF
  215.   base_time%=TIMER
  216.   FOR i%=1 TO 3
  217.     seq%(i%)=0
  218.     repeat_count%(i%-1)=0
  219.     repeat_sign%(i%-1)=0
  220.     play_stop%(i%-1)=vclen%(i%-1)
  221.     elapsed_microbeats%(i%-1)=0
  222.     micro_beat%(i%)=0
  223.     next_bar_line%=bar_length%
  224.     next_event%(i%)=base_time%+slowness*micro_beat%(i%)
  225.     IF seq%(i%)<=play_stop%(i%-1)
  226.       voice_end_flag%(i%)=0
  227.     ELSE
  228.       voice_end_flag%(i%)=1
  229.     ENDIF
  230.     @set_volume(i%-1,10)
  231.     @set_tone_period(i%-1,5)
  232.   NEXT i%
  233.   memptr%=0
  234.   k%=0
  235.   '
  236.   ' ready to start
  237.   @disable_noise_channels
  238.   REPEAT
  239.     @play_next_notes
  240.     ' the r